﻿using LunarSF.SHomeWorkshop.LunarMarkdownEditor.Widgets.MindMap;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor.GraphicDemonstrator
{
    /// <summary>
    /// GraphicDemonstrator.xaml 的交互逻辑
    /// </summary>
    public partial class GraphicDemonstrator : Window
    {
        public GraphicDemonstrator(List<DemoResourceGroup> groups)
        {
            InitializeComponent();

            this.resourceGroups = groups;
            if (groups != null && groups.Count > 0)
            {
                foreach (var group in groups)
                {
                    group.GraphicDemonstrator = this;
                }
            }

            keyBoardPopup.PlacementTarget = btnVirtualKeyBoard;
            keyBoardPopup.KeyPressed += KeyBoard_KeyPressed;



            // 与树型图控件相关的初始化
            this.mindMapView.btnSnapItAndInsertToDocument.Visibility = Visibility.Collapsed;

            mindMapView.baseBoard.ToolTip = "[Esc 或 鼠标左键双击空白区域]退出预览";
            mindMapView.btnFirst.ToolTip = "[Ctrl+PageUp]显示第一个根节点";
            mindMapView.btnPreview.ToolTip = "[PageUp]显示前一个根节点";
            mindMapView.btnPreviewRootElement.ToolTip = "[Ctrl+Home]显示当前节点所在根节点";
            mindMapView.btnParentElement.ToolTip = "[Home]显示上级节点";
            mindMapView.btnNext.ToolTip = "[PageDown]显示后一个根节点";
            mindMapView.btnLast.ToolTip = "[Ctrl+PageDown]显示最后一个根节点";
            mindMapView.btnSnapIt.ToolTip = "[Ctrl+C]将当前导图复制到剪贴板";
            mindMapView.btnSaveMindMapImage.ToolTip = "[Ctrl+S]保存当前导图";

            mindMapView.btnPreviewAsListView.ToolTip = "[1]列表视图";
            mindMapView.btnPreviewAsDownOrgView.ToolTip = "[2]下开口组织结构图";
            mindMapView.btnPreviewAsLeftFish.ToolTip = "[3]左向鱼骨图";
            mindMapView.btnPreviewAsRightOrgView.ToolTip = "[4]右武器组织结构图";
            mindMapView.btnPreviewAsDefaultMindMapView.ToolTip = "[5]思维导图\r\n[0或按Ctrl并单击]全子节导图";
            mindMapView.btnPreviewAsLeftOrgView.ToolTip = "[6]左开口组织结构图";
            mindMapView.btnPreviewAsAncestorView.ToolTip = "[7]祖先节点图";
            mindMapView.btnPreviewAsUpOrgView.ToolTip = "[8]上开口组织结构图";
            mindMapView.btnPreviewAsRightFish.ToolTip = "[9]右向鱼骨图";

            mindMapView.btnShowTools.ToolTip = "[Space]显示视图切换按钮";

            mindMapView.btnDemonstratResources.ToolTip = "展示当前标题直接下级图文资源节点";

            mindMapView.DisplayElementChanged += MindMapView_DisplayElementChanged;
            this.Loaded += GraphicDemonstrator_Loaded;
        }

        private void GraphicDemonstrator_Loaded(object sender, RoutedEventArgs e)
        {
            this.ShowGroup(0);
        }

        private void MindMapView_DisplayElementChanged(object sender, DisplayElementChangedArgs e)
        {
            var resourceElementCount = 0;
            var reg = new Regex(@"^[ 　\t]*[!！]?[ 　\t]*\[.*?\]\(.*?\)[ 　\t]*$");

            var groups = new List<DemoResourceGroup>();
            var group = new DemoResourceGroup();
            groups.Add(group);
            var trimChars = new char[] { ' ', '　', '\t' };

            foreach (var el in e.NewElement.Children)
            {
                DemoResourceInfo dri;
                switch (el.Type)
                {
                    case TreeElementType.ImageLink:
                        dri = new DemoResourceInfo()
                        {
                            AbsolutePath = el.LinkedImageRealPath,
                            LinkTitle = el.Content,
                            LinkType = "Image",
                            RelativePath = el.RelativePath,
                        };
                        break;
                    case TreeElementType.FileLink:
                        dri = new DemoResourceInfo()
                        {
                            AbsolutePath = el.LinkdeFileRealPath,
                            LinkTitle = el.Content,
                            LinkType = "Html",
                            RelativePath = el.RelativePath,
                        };
                        break;
                    default:
                        continue;
                }

                group.Add(dri);

                resourceElementCount++;
            }

            if (resourceElementCount > 0)
            {
                this.resourceGroups = groups;
                if (groups != null && groups.Count > 0)
                {
                    foreach (var gp in groups)
                    {
                        gp.GraphicDemonstrator = this;
                    }
                }

                this.ShowGroup(0, false);
            }
            else
            {
                this.resourceGroups?.Clear();
                this.ugResources?.Children?.Clear();
                this.gdResources.Visibility = Visibility.Collapsed;
                this.gdTools.Visibility = Visibility.Collapsed;
            }
        }

        public TreeElement CurDisplayingElement { get; set; }

        private string themeText;

        public string ThemeText
        {
            get { return this.themeText; }
            set
            {
                this.themeText = value;
                if (this.themeText.ToLower() == "dark")
                {
                    this.Background = BrushManager.GetBrush("BlackSmoke");
                }
                else
                {
                    this.Background = Brushes.WhiteSmoke;
                }
            }
        }

        private void KeyBoard_KeyPressed(object sender, Widgets.KeyPressedEventArgs e)
        {
            if (e.KeyText == "Enter")
            {
                Globals.MainWindow.cmbSearchResource.Text = keyBoardPopup.Keyboard.Text;
                Globals.MainWindow.SearchInWorkspace();

                if (Globals.MainWindow.SearchedWorkspaceItemlist.Count > 0)
                {
                    keyBoardPopup.Keyboard.ClearText();
                }

                var findedwtvis = Globals.MainWindow.SearchedWorkspaceItemlist;
                SearchResources(findedwtvis);
                keyBoardPopup.IsOpen = false;
            }
            else if (e.KeyText.StartsWith("SizeChanged"))
            {
                KeyBoardPopup_Opened(sender, e);
            }
        }

        private void SearchResources(List<WorkspaceTreeViewItem> finedwtvis)
        {
            ResourceGroups.Clear();

            var checkedWtvis = finedwtvis;
            var rcount = 0;

            DemoResourceGroup group = null;
            foreach (var wtvi in checkedWtvis)
            {
                if (rcount % 6 == 0)
                {
                    if (group != null && group.Count > 0)
                    {
                        ResourceGroups.Add(group);
                    }
                    group = new DemoResourceGroup();
                    group.GraphicDemonstrator = this;
                    group.Title = "";
                }

                switch (wtvi.ItemType)
                {
                    case WorkspaceTreeViewItem.Type.Folder:
                    case WorkspaceTreeViewItem.Type.File:
                        {
                            var rpath = wtvi.RelativePath;
                            group.Add(new DemoResourceInfo()
                            {
                                RelativePath = rpath,
                                LinkType = "Html",
                                LinkTitle = wtvi.Title,
                            });
                            rcount++;
                            break;
                        }
                    case WorkspaceTreeViewItem.Type.Image:
                        {
                            var rpath = wtvi.RelativePath;
                            group.Add(new DemoResourceInfo()
                            {
                                RelativePath = rpath,
                                LinkType = "Image",
                                LinkTitle = wtvi.Title,
                            });
                            rcount++;
                            break;
                        }
                        // 暂时不支持音、视频
                }
            }

            if (group != null && group.Count > 0)
            {
                ResourceGroups.Add(group);
            }

            if (ResourceGroups.Count > 0)
            {
                ShowGroup(0);
            }
        }

        private void BtnVirtualKeyBoard_Click(object sender, RoutedEventArgs e)
        {
            keyBoardPopup.IsOpen = !keyBoardPopup.IsOpen;
        }

        private VirtualKeyboardPopup keyBoardPopup = new VirtualKeyboardPopup();

        public Canvas MainCanvas { get { return mainCanvas; } }

        private List<DemoResourceGroup> resourceGroups;

        public List<DemoResourceGroup> ResourceGroups
        {
            get
            {
                if (resourceGroups == null)
                {
                    resourceGroups = new List<DemoResourceGroup>();
                }
                return resourceGroups;
            }
        }

        private void btnSwitch_Click(object sender, RoutedEventArgs e)
        {
            if (Grid.GetColumn(gdTools) == 0)  // 如果当前在左侧
            {
                // 返回右侧
                Grid.SetColumn(gdTools, 2);
                Grid.SetColumn(btnSwitch, 0);
                Grid.SetColumn(ugResources, 1);
                cdSwitch.Width = new GridLength(1, GridUnitType.Auto);
                cdResources.Width = new GridLength(1, GridUnitType.Star);
            }
            else
            {
                // 在右侧，切换到左侧
                Grid.SetColumn(gdTools, 0);
                Grid.SetColumn(btnSwitch, 1);
                Grid.SetColumn(ugResources, 0);
                cdSwitch.Width = new GridLength(1, GridUnitType.Star);
                cdResources.Width = new GridLength(1, GridUnitType.Auto);
            }

            this.InvalidateVisual();
            this.UpdateLayout();

            btn_layout_default_Click(sender, e);
        }

        private void btn_layout_default_Click(object sender, RoutedEventArgs e)
        {
            var cards = OpenedCards;

            if (cards.Count <= 0) return;

            var hspan = 40;
            var vspan = 40;

            var leftTop = this.mainCanvas.PointToScreen(new Point(20, 20));
            var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

            for (int i = 0; i < cards.Count; i++)
            {
                cards[i].Left = leftTop.X + hspan * i;
                cards[i].Top = leftTop.Y + vspan * i;

                cards[i].Width = this.mainCanvas.ActualWidth - hspan * cards.Count;
                cards[i].Height = this.mainCanvas.ActualHeight - vspan * cards.Count;

                cards[i].Activate();
            }
        }

        public DemoResourceCard ActivedCard { get; set; } = null;

        private void btn_layout_maxsize_Click(object sender, RoutedEventArgs e)
        {
            var activedCard = ActivedCard;
            if (activedCard != null)
            {
                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                //var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                activedCard.Width = mainCanvas.ActualWidth;
                activedCard.Height = mainCanvas.ActualHeight;

                activedCard.Left = leftTop.X;
                activedCard.Top = leftTop.Y;
            }
            else
            {
                MessageBox.Show("请先选中一个资源演示窗口！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
        }

        private void btn_layout_minsize_Click(object sender, RoutedEventArgs e)
        {
            var activedCard = ActivedCard;
            if (activedCard != null)
            {
                activedCard.Close();
                activedCard.MasterResourceButton.IsChecked = false;

                ActivedCard = null;
            }
            else
            {
                MessageBox.Show("请先选中一个资源演示窗口！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
        }

        private List<DemoResourceCard> OpenedCards
        {
            get
            {
                var cards = new List<DemoResourceCard>();
                foreach (var element in this.ugResources.Children)
                {
                    if (element is DemoResourceButton dbtn)
                    {
                        if (dbtn.ResourceCard.Visibility == Visibility.Visible)
                        {
                            cards.Add(dbtn.ResourceCard);
                        }
                    }
                }
                return cards;
            }
        }

        private void btn_layout_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var tag = (sender as Button).Tag as string;
                switch (tag)
                {
                    case "2-h":    // 横向2个
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 2)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth / 2;
                                cards[0].Height = mainCanvas.ActualHeight;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 2;
                                cards[1].Height = mainCanvas.ActualHeight;
                                cards[1].Left = leftTop.X + cards[0].Width;
                                cards[1].Top = leftTop.Y;
                            }
                            break;
                        }
                    case "2-v":    //  纵向2个
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 2)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth;
                                cards[0].Height = mainCanvas.ActualHeight / 2;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth;
                                cards[1].Height = mainCanvas.ActualHeight / 2;
                                cards[1].Left = leftTop.X;
                                cards[1].Top = leftTop.Y + cards[0].Height;
                            }
                            break;
                        }
                    case "3-l":   // 左1右2
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 3)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth / 2;
                                cards[0].Height = mainCanvas.ActualHeight;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 2;
                                cards[1].Height = mainCanvas.ActualHeight / 2;
                                cards[1].Left = leftTop.X + cards[0].Width;
                                cards[1].Top = leftTop.Y;

                                cards[2].Width = mainCanvas.ActualWidth / 2;
                                cards[2].Height = mainCanvas.ActualHeight / 2;
                                cards[2].Left = leftTop.X + cards[1].Width;
                                cards[2].Top = leftTop.Y + cards[1].Height;
                            }
                            break;
                        }
                    case "3-t":   // 上1下2
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 3)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth;
                                cards[0].Height = mainCanvas.ActualHeight / 2;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 2;
                                cards[1].Height = mainCanvas.ActualHeight / 2;
                                cards[1].Left = leftTop.X;
                                cards[1].Top = leftTop.Y + cards[0].Height;

                                cards[2].Width = mainCanvas.ActualWidth / 2;
                                cards[2].Height = mainCanvas.ActualHeight / 2;
                                cards[2].Left = leftTop.X + cards[1].Width;
                                cards[2].Top = leftTop.Y + cards[1].Height;
                            }
                            break;
                        }
                    case "3-r":   // 右1左2
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 3)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth / 2;
                                cards[0].Height = mainCanvas.ActualHeight / 2;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 2;
                                cards[1].Height = mainCanvas.ActualHeight / 2;
                                cards[1].Left = leftTop.X;
                                cards[1].Top = leftTop.Y + cards[0].Height;

                                cards[2].Width = mainCanvas.ActualWidth / 2;
                                cards[2].Height = mainCanvas.ActualHeight;
                                cards[2].Left = leftTop.X + cards[0].Width;
                                cards[2].Top = leftTop.Y;
                            }
                            break;
                        }
                    case "3-b":   //  下1上2
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 3)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth / 2;
                                cards[0].Height = mainCanvas.ActualHeight / 2;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 2;
                                cards[1].Height = mainCanvas.ActualHeight / 2;
                                cards[1].Left = leftTop.X + cards[0].Width;
                                cards[1].Top = leftTop.Y;

                                cards[2].Width = mainCanvas.ActualWidth;
                                cards[2].Height = mainCanvas.ActualHeight / 2;
                                cards[2].Left = leftTop.X;
                                cards[2].Top = leftTop.Y + cards[0].Height;
                            }
                            break;
                        }
                    case "3-a":   // 三个横排
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 3)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth / 3;
                                cards[0].Height = mainCanvas.ActualHeight;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 3;
                                cards[1].Height = mainCanvas.ActualHeight;
                                cards[1].Left = leftTop.X + cards[0].Width;
                                cards[1].Top = leftTop.Y;

                                cards[2].Width = mainCanvas.ActualWidth / 3;
                                cards[2].Height = mainCanvas.ActualHeight;
                                cards[2].Left = leftTop.X + cards[0].Width * 2;
                                cards[2].Top = leftTop.Y;
                            }
                            break;
                        }
                    case "4":     // 田字布局
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 4)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth / 2;
                                cards[0].Height = mainCanvas.ActualHeight / 2;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 2;
                                cards[1].Height = mainCanvas.ActualHeight / 2;
                                cards[1].Left = leftTop.X + cards[0].Width;
                                cards[1].Top = leftTop.Y;

                                cards[2].Width = mainCanvas.ActualWidth / 2;
                                cards[2].Height = mainCanvas.ActualHeight / 2;
                                cards[2].Left = leftTop.X;
                                cards[2].Top = leftTop.Y + cards[0].Height;

                                cards[3].Width = mainCanvas.ActualWidth / 2;
                                cards[3].Height = mainCanvas.ActualHeight / 2;
                                cards[3].Left = leftTop.X + cards[0].Width;
                                cards[3].Top = leftTop.Y + cards[0].Height;
                            }
                            break;
                        }
                    case "5-l":   // 左1右4（4呈田字布局）
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 5)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth / 3;
                                cards[0].Height = mainCanvas.ActualHeight;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 3;
                                cards[1].Height = mainCanvas.ActualHeight / 2;
                                cards[1].Left = leftTop.X + cards[0].Width;
                                cards[1].Top = leftTop.Y;

                                cards[2].Width = mainCanvas.ActualWidth / 3;
                                cards[2].Height = mainCanvas.ActualHeight / 2;
                                cards[2].Left = leftTop.X + cards[0].Width * 2;
                                cards[2].Top = leftTop.Y;

                                cards[3].Width = mainCanvas.ActualWidth / 3;
                                cards[3].Height = mainCanvas.ActualHeight / 2;
                                cards[3].Left = leftTop.X + cards[0].Width;
                                cards[3].Top = leftTop.Y + cards[2].Height;

                                cards[4].Width = mainCanvas.ActualWidth / 3;
                                cards[4].Height = mainCanvas.ActualHeight / 2;
                                cards[4].Left = leftTop.X + cards[0].Width * 2;
                                cards[4].Top = leftTop.Y + cards[2].Height;
                            }
                            break;
                        }
                    case "5-t":   // 上1下4（4呈田字布局）
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 5)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth;
                                cards[0].Height = mainCanvas.ActualHeight / 3;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 2;
                                cards[1].Height = mainCanvas.ActualHeight / 3;
                                cards[1].Left = leftTop.X;
                                cards[1].Top = leftTop.Y + cards[0].Height;

                                cards[2].Width = mainCanvas.ActualWidth / 2;
                                cards[2].Height = mainCanvas.ActualHeight / 3;
                                cards[2].Left = leftTop.X + cards[1].Width;
                                cards[2].Top = leftTop.Y + cards[0].Height;

                                cards[3].Width = mainCanvas.ActualWidth / 2;
                                cards[3].Height = mainCanvas.ActualHeight / 3;
                                cards[3].Left = leftTop.X;
                                cards[3].Top = leftTop.Y + cards[0].Height * 2;

                                cards[4].Width = mainCanvas.ActualWidth / 2;
                                cards[4].Height = mainCanvas.ActualHeight / 3;
                                cards[4].Left = leftTop.X + cards[3].Width;
                                cards[4].Top = leftTop.Y + cards[0].Height * 2;
                            }
                            break;
                        }
                    case "5-r":   // 右1左4（4呈田字布局）
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 5)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth / 3;
                                cards[0].Height = mainCanvas.ActualHeight / 2;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 3;
                                cards[1].Height = mainCanvas.ActualHeight / 2;
                                cards[1].Left = leftTop.X + cards[0].Width;
                                cards[1].Top = leftTop.Y;

                                cards[2].Width = mainCanvas.ActualWidth / 3;
                                cards[2].Height = mainCanvas.ActualHeight / 2;
                                cards[2].Left = leftTop.X;
                                cards[2].Top = leftTop.Y + cards[0].Height;

                                cards[3].Width = mainCanvas.ActualWidth / 3;
                                cards[3].Height = mainCanvas.ActualHeight / 2;
                                cards[3].Left = leftTop.X + cards[0].Width;
                                cards[3].Top = leftTop.Y + cards[0].Height;

                                cards[4].Width = mainCanvas.ActualWidth / 3;
                                cards[4].Height = mainCanvas.ActualHeight;
                                cards[4].Left = leftTop.X + cards[0].Width * 2;
                                cards[4].Top = leftTop.Y;
                            }
                            break;
                        }
                    case "5-b":   // 下1上4（4呈田字布局）
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 5)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth / 2;
                                cards[0].Height = mainCanvas.ActualHeight / 3;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 2;
                                cards[1].Height = mainCanvas.ActualHeight / 3;
                                cards[1].Left = leftTop.X + cards[0].Width;
                                cards[1].Top = leftTop.Y;

                                cards[2].Width = mainCanvas.ActualWidth / 2;
                                cards[2].Height = mainCanvas.ActualHeight / 3;
                                cards[2].Left = leftTop.X;
                                cards[2].Top = leftTop.Y + cards[0].Height;

                                cards[3].Width = mainCanvas.ActualWidth / 2;
                                cards[3].Height = mainCanvas.ActualHeight / 3;
                                cards[3].Left = leftTop.X + cards[0].Width;
                                cards[3].Top = leftTop.Y + cards[0].Height;

                                cards[4].Width = mainCanvas.ActualWidth;
                                cards[4].Height = mainCanvas.ActualHeight / 3;
                                cards[4].Left = leftTop.X;
                                cards[4].Top = leftTop.Y + cards[0].Height * 2;
                            }
                            break;
                        }
                    case "6-h":
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 6)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth / 2;
                                cards[0].Height = mainCanvas.ActualHeight / 3;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 2;
                                cards[1].Height = mainCanvas.ActualHeight / 3;
                                cards[1].Left = leftTop.X + cards[0].Width;
                                cards[1].Top = leftTop.Y;

                                cards[2].Width = mainCanvas.ActualWidth / 2;
                                cards[2].Height = mainCanvas.ActualHeight / 3;
                                cards[2].Left = leftTop.X;
                                cards[2].Top = leftTop.Y + cards[0].Height;

                                cards[3].Width = mainCanvas.ActualWidth / 2;
                                cards[3].Height = mainCanvas.ActualHeight / 3;
                                cards[3].Left = leftTop.X + cards[0].Width;
                                cards[3].Top = leftTop.Y + cards[0].Height;

                                cards[4].Width = mainCanvas.ActualWidth / 2;
                                cards[4].Height = mainCanvas.ActualHeight / 3;
                                cards[4].Left = leftTop.X;
                                cards[4].Top = leftTop.Y + cards[0].Height * 2;

                                cards[5].Width = mainCanvas.ActualWidth / 2;
                                cards[5].Height = mainCanvas.ActualHeight / 3;
                                cards[5].Left = leftTop.X + cards[0].Width;
                                cards[5].Top = leftTop.Y + cards[0].Height * 2;
                            }
                            break;
                        }
                    case "6-v":
                        {
                            var cards = OpenedCards;
                            if (cards.Count == 6)
                            {
                                var leftTop = this.mainCanvas.PointToScreen(new Point(0, 0));
                                var rightBottom = this.mainCanvas.PointToScreen(new Point(this.mainCanvas.ActualWidth, this.mainCanvas.ActualHeight));

                                cards[0].Width = mainCanvas.ActualWidth / 3;
                                cards[0].Height = mainCanvas.ActualHeight / 2;
                                cards[0].Left = leftTop.X;
                                cards[0].Top = leftTop.Y;

                                cards[1].Width = mainCanvas.ActualWidth / 3;
                                cards[1].Height = mainCanvas.ActualHeight / 2;
                                cards[1].Left = leftTop.X + cards[0].Width;
                                cards[1].Top = leftTop.Y;

                                cards[2].Width = mainCanvas.ActualWidth / 3;
                                cards[2].Height = mainCanvas.ActualHeight / 2;
                                cards[2].Left = leftTop.X + cards[0].Width * 2;
                                cards[2].Top = leftTop.Y;

                                cards[3].Width = mainCanvas.ActualWidth / 3;
                                cards[3].Height = mainCanvas.ActualHeight / 2;
                                cards[3].Left = leftTop.X;
                                cards[3].Top = leftTop.Y + cards[0].Height;

                                cards[4].Width = mainCanvas.ActualWidth / 3;
                                cards[4].Height = mainCanvas.ActualHeight / 2;
                                cards[4].Left = leftTop.X + cards[0].Width;
                                cards[4].Top = leftTop.Y + cards[0].Height;

                                cards[5].Width = mainCanvas.ActualWidth / 3;
                                cards[5].Height = mainCanvas.ActualHeight / 2;
                                cards[5].Left = leftTop.X + cards[0].Width * 2;
                                cards[5].Top = leftTop.Y + cards[0].Height;
                            }
                            break;
                        }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
            }
        }

        private void btnPreviewGroup_Click(object sender, RoutedEventArgs e)
        {
            this.ShowGroup(--groupIndex);
        }

        private void btnNextGroup_Click(object sender, RoutedEventArgs e)
        {
            this.ShowGroup(++groupIndex);
        }

        private int groupIndex = 0;

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.CurDisplayingElement != null)
            {
                this.mindMapView.DisplayMindMap(this.CurDisplayingElement);
                return;
            }

            if (this.ResourceGroups.Count > 0)
            {
                this.ShowGroup(0, false);
            }
        }

        internal Grid GdTools { get { return this.gdTools; } }

        public UniformGrid UgResources { get { return ugResources; } }

        private void ShowGroup(int index, bool showFstCard = true)
        {
            if (index < 0 || this.ResourceGroups == null || this.ResourceGroups.Count <= 0 || index >= this.ResourceGroups.Count) return;

            ugResources.Children.Clear();

            this.mainCanvas.Children.Clear();

            this.groupIndex = index;

            var group = this.ResourceGroups[this.groupIndex];

            if (group.Count <= 0)
            {
                // MessageBox.Show("此分组中无资源！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                gdTools.Visibility = Visibility.Collapsed;
                gdResources.Visibility = Visibility.Collapsed;
                return;
            }
            else
            {
                gdTools.Visibility = Visibility.Visible;
                gdResources.Visibility = Visibility.Visible;
            }

            switch(mindMapView.Theme)
            {
                case MindMapView.ViewTheme.Dark:
                    {
                        gdTools.Background = BrushManager.GetBrush("BlackSmoke");
                        gdResources.Background = BrushManager.GetBrush("BlackSmoke");
                        this.themeText = "dark";
                        break;
                    }
                case MindMapView.ViewTheme.Light:
                    {
                        gdTools.Background = Brushes.WhiteSmoke;
                        gdResources.Background = Brushes.WhiteSmoke;
                        this.themeText = "light";
                        break;
                    }
            }

            DemoResourceButton fstbtn = null;
            foreach (var ri in group.Resources)
            {
                var dbtn = new DemoResourceButton(this, ri, group.GraphicDemonstrator.MainCanvas, this);

                dbtn.ThemeText = this.themeText;

                ugResources.Children.Add(dbtn);
                if (fstbtn == null) fstbtn = dbtn;
            }

            tbGroupTitle.Text = group.Title;

            if (string.IsNullOrWhiteSpace(tbGroupTitle.Text))
            {
                rUnderLine.Visibility =
                    tbGroupTitle.Visibility = Visibility.Collapsed;
            }
            else
            {
                rUnderLine.Visibility =
                    tbGroupTitle.Visibility = Visibility.Visible;
            }

            tbGroupIndex.Text = $"{index + 1} / {this.ResourceGroups.Count}";

            mainCanvas.InvalidateArrange();
            mainCanvas.UpdateLayout();

            if (showFstCard)
            {
                fstbtn?.ShowCard();
            }
        }

        private void mainCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            foreach (var element in mainCanvas.Children)
            {
                if (element is DemoResourceCard card)
                {
                    card.Height = mainCanvas.ActualHeight / 2;
                    card.Width = mainCanvas.ActualWidth / 2;
                }
            }
        }

        private void btnVirtualKeyBoard_Initialized(object sender, EventArgs e)
        {
            keyBoardPopup.Placement = PlacementMode.Absolute;
            keyBoardPopup.PlacementTarget = btnVirtualKeyBoard;

            keyBoardPopup.Opened += KeyBoardPopup_Opened;
        }

        private void KeyBoardPopup_Opened(object sender, EventArgs e)
        {
            var point = btnVirtualKeyBoard.PointToScreen(new Point(0, 0));

            if (Environment.OSVersion.Version.Major > 6 ||
                (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1))  // win 8 以上（6.2）
            {
                keyBoardPopup.HorizontalOffset = point.X - keyBoardPopup.Width + btnVirtualKeyBoard.ActualWidth + 6;
                keyBoardPopup.VerticalOffset = point.Y - keyBoardPopup.Height + 6;
            }
            else
            {
                keyBoardPopup.HorizontalOffset = point.X - keyBoardPopup.Width + btnVirtualKeyBoard.ActualWidth;
                keyBoardPopup.VerticalOffset = point.Y - keyBoardPopup.Height;
            }
        }

        private void MetroWindow_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            {
                //var answer = LMessageBox.ShowQuestion("要退出图文资源演示器窗口吗？");
                //if (answer != MessageBoxResult.Yes) return;

                this.Close();
                return;
            }

            L.GetKeyboardState(out bool isAlt, out bool isShift, out bool isCtrl);

            this.Focus();   // 不是这个造成的

            switch (e.Key)
            {
                case Key.Escape:
                    {
                        this.Close(); break;
                    }
                case Key.PageDown:
                    {
                        if (isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.ShowLastRootElement();
                        }
                        else
                        {
                            mindMapView.ShowNextRootElement();
                        }
                        e.Handled = true;
                        break;
                    }
                case Key.PageUp:
                    {
                        if (isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.ShowFirstRootElement();
                        }
                        else
                        {
                            mindMapView.ShowPreviewRootElement();
                        }
                        e.Handled = true;
                        break;
                    }
                case Key.Home:
                    {
                        if (isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.ShowCurrentRootElement();
                        }
                        else
                        {
                            mindMapView.ShowParentElement();
                        }
                        e.Handled = true;
                        break;
                    }
                case Key.C:
                    {
                        if (isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.SnapIt();
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.S:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.SaveMindMapImage();
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D0:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.PreviewAsFullMindMapView(mindMapView.btnPreviewAsDefaultMindMapView.Tag.ToString(), true);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D1:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.PreviewAsListView(mindMapView.btnPreviewAsListView.Tag.ToString(), true);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D2:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.PreviewAsOrgView(mindMapView.btnPreviewAsDownOrgView.Tag.ToString(), true);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D3:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.PreviewAsFishBone(mindMapView.btnPreviewAsLeftFish.Tag.ToString(), true);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D4:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.PreviewAsOrgView(mindMapView.btnPreviewAsRightOrgView.Tag.ToString(), true);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D5:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.PreviewAsDefaultMindMapView(mindMapView.btnPreviewAsDefaultMindMapView.Tag.ToString(), true);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D6:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.PreviewAsOrgView(mindMapView.btnPreviewAsLeftOrgView.Tag.ToString(), true);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D7:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.PreviewAsAncestorView(mindMapView.btnPreviewAsAncestorView.Tag.ToString(), true);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D8:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.PreviewAsOrgView(mindMapView.btnPreviewAsUpOrgView.Tag.ToString(), true);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D9:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            mindMapView.PreviewAsFishBone(mindMapView.btnPreviewAsRightFish.Tag.ToString(), true);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.Space:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            if (mindMapView.spViews.Visibility == Visibility.Visible)
                            {
                                mindMapView.spViews.Visibility = Visibility.Collapsed;
                            }
                            else
                            {
                                mindMapView.spViews.Visibility = Visibility.Visible;
                            }
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.Enter:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            MindMapTitle mmt = null;
                            foreach (var ue in mindMapView.MainCanvas.Children)
                            {
                                var title = ue as MindMapTitle;
                                if (title == null) continue;

                                if (title.IsSelectedTitle)
                                {
                                    mmt = title;
                                    break;
                                }
                            }

                            if (mmt != null)
                            {
                                mindMapView.DisplayMindMap(mmt.Element);
                            }
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.Left:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            var selTitle = mindMapView.SelectedTitle;
                            if (selTitle == null) return;
                            var destTitle = selTitle.LeftTitle;
                            if (destTitle == null) return;
                            mindMapView.SelectedTitle = destTitle;
                            selTitle.IsSelectedTitle = false;
                            destTitle.IsSelectedTitle = true;
                        }
                        break;
                    }
                case Key.Right:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            var selTitle = mindMapView.SelectedTitle;
                            if (selTitle == null) return;
                            var destTitle = selTitle.RightTitle;
                            if (destTitle == null) return;
                            mindMapView.SelectedTitle = destTitle;
                            selTitle.IsSelectedTitle = false;
                            destTitle.IsSelectedTitle = true;
                        }
                        break;
                    }
                case Key.Up:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            var selTitle = mindMapView.SelectedTitle;
                            if (selTitle == null) return;
                            var destTitle = selTitle.TopTitle;
                            if (destTitle == null) return;
                            mindMapView.SelectedTitle = destTitle;
                            selTitle.IsSelectedTitle = false;
                            destTitle.IsSelectedTitle = true;
                        }
                        break;
                    }
                case Key.Down:
                    {
                        if (!isCtrl && !isAlt && !isShift)
                        {
                            var selTitle = mindMapView.SelectedTitle;
                            if (selTitle == null) return;
                            var destTitle = selTitle.BottomTitle;
                            if (destTitle == null) return;
                            mindMapView.SelectedTitle = destTitle;
                            selTitle.IsSelectedTitle = false;
                            destTitle.IsSelectedTitle = true;
                        }
                        break;
                    }
                    // 无论是在这里还是在 MainWindow 通过 Apps 快捷键调用演示窗口总会崩溃，但通过鼠标就不会有问题。
                    //case Key.Apps:
                    //    {
                    //        if (!isAlt && !isShift && isCtrl)
                    //        {
                    //            mindMapView.DemonstratResources();
                    //            e.Handled = true;
                    //        }
                    //        break;
                    //    }
            }
        }

        private void MetroWindow_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            //var answer = LMessageBox.ShowQuestion("要退出图文资源演示器窗口吗？");
            //if (answer != MessageBoxResult.Yes) return;

            this.Close();
        }

        private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 1)
            {
                if (gdTools.Visibility == Visibility.Collapsed && gdResources.Visibility == Visibility.Collapsed)
                {
                    if (this.ugResources.Children.Count > 0)
                    {
                        gdResources.Visibility = Visibility.Visible;
                        gdTools.Visibility = Visibility.Visible;
                    }
                }
                else if (gdTools.Visibility == Visibility.Visible && gdResources.Visibility == Visibility.Visible)
                {
                    gdResources.Visibility = Visibility.Collapsed;
                    gdTools.Visibility = Visibility.Collapsed;

                    if (this.ugResources.Children.Count > 0)
                    {
                        foreach (var ui in ugResources.Children)
                        {
                            var btn = ui as DemoResourceButton;
                            if (btn == null) continue;

                            btn.HideCard();
                        }
                    }
                }
            }
        }
    }
}
